package com.trainshop.sms.manage;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

public class SmsManager {
	//短信通道集合
	private static List<SmsChannelInterface> channelList = new ArrayList<SmsChannelInterface>();
	//记录手机号和短信通道(用于处理通道短信发送成功并返回成功标志位，但是用户没有收到短信再次点击发送的情况，用户再次点击时切换短信通道发送短信)
	private static Map<String,MessageRecord> messageChannelMapHistory = new HashMap<String, MessageRecord>();
	
	private static ThreadPoolExecutor tpe;
	private static SmsManager instance;
	
	//读取线程池配置
	static ResourceBundle bundle=PropertyResourceBundle.getBundle("sms");
	static int corePoolSize = Integer.parseInt(bundle.getString("corePoolSize"));
	static int maximumPoolSize = Integer.parseInt(bundle.getString("maximumPoolSize"));
	static int keepAliveTime = Integer.parseInt(bundle.getString("keepAliveTime"));
	static int maxQueueSize = Integer.parseInt(bundle.getString("maxQueueSize"));
	
	
	/**
	 * 单例、初始化
	 */
	public synchronized static SmsManager getInstance(){
		if(instance == null){
			instance = new SmsManager();
		}
		//任务队列中的最大任务数
//		int maxQueueSize = 10;
		tpe = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(maxQueueSize),  
	            new ThreadPoolExecutor.DiscardOldestPolicy()); 
		instance.initChannel();
		
		cleanHistory();
		
		return instance;
	}
	
	/**
	 * 初始化短信通道
	 */
	private void initChannel(){
		AliSend ali = new AliSend();
		YiMeiSend yimei = new YiMeiSend();
		channelList.add(ali);
		channelList.add(yimei);
	}

	
	/**
	 * 每20分钟清扫一次手机号和短信通道对应关系的map集合历史记录
	 */
	private static void cleanHistory(){
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            public void run() {
            	Iterator it=instance.messageChannelMapHistory.keySet().iterator();    
            	while(it.hasNext()){    
            	     String key=it.next().toString();
            	     MessageRecord value=instance.messageChannelMapHistory.get(key);
            	     //最近5分钟内的对应关系不允许被清除
            	     if((new Date().getTime() - value.getRecordTime().getTime())/60000 > 5){
            	    	 instance.messageChannelMapHistory.remove(key);
            	     }
            	}
            }
        }, 1000, 1200000);
	}
	
	
	/**
	 * 发短信方法
	 * @param phone 电话号
	 * @param content 短信内容
	 * @throws WrongPhoneException 
	 */
	public void send(String phone,String content,String template) throws WrongPhoneException{
		String REGEX_MOBILE = "(13\\d|14[57]|15[^4,\\D]|17[678]|18\\d)\\d{8}|170[059]\\d{7}";
		if(!Pattern.matches(REGEX_MOBILE, phone)){
			throw new WrongPhoneException("手机号码不正确");
		}
		TextMessage message = new TextMessage();
		message.setPhone(phone);
		message.setContent(content);
		message.setTemplate(template);
		
		MessageTask messageTask = new MessageTask(message);
		tpe.execute(messageTask);
	}
	
	
	/**
	 * 发短信方法
	 * @param phone 电话号
	 * @param content 短信内容
	 * @throws WrongPhoneException 
	 */
	public void send(String phone,String content,String template,Integer chanelIndex) throws WrongPhoneException{
		String REGEX_MOBILE = "(13\\d|14[57]|15[^4,\\D]|17[678]|18\\d)\\d{8}|170[059]\\d{7}";
		if(!Pattern.matches(REGEX_MOBILE, phone)){
			throw new WrongPhoneException("手机号码不正确");
		}
		TextMessage message = new TextMessage();
		message.setPhone(phone);
		message.setContent(content);
		message.setTemplate(template);
		message.setChanelIndex(chanelIndex);
		
		MessageTask messageTask = new MessageTask(message);
		tpe.execute(messageTask);
	}
	
	
	public static class MessageTask implements Runnable{
		private TextMessage message;
		
		public MessageTask(TextMessage message) {
			super();
			this.message = message;
		}

		@Override
		public void run() {
			sendMessage(message);
		}
		
		private void sendMessage(TextMessage message){
			
			//如果发送了20次还未成功，则停止发送
			if(messageChannelMapHistory.get(message.getPhone()) != null){
				if(messageChannelMapHistory.get(message.getPhone()).getSendNum()>=20){
					return;
				}
			}
			
			//指定通道发送短信
			if(message.getChanelIndex() != null){
				try{
					int returnFlag = channelList.get(message.getChanelIndex()).sendMessage(message);
					if(returnFlag != 0){
						addToMessageChannelMapHistory(message.getChanelIndex(),message,false);
						tpe.execute(this);
					}
				}catch(Exception e){
					addToMessageChannelMapHistory(message.getChanelIndex(),message,false);
					tpe.execute(this);
					e.printStackTrace();
				}
				return;
			}
			
			//所有通道参与发送短信
			int channelIndex = 0;
			try{
				//如果上次发送失败
				if(messageChannelMapHistory.get(message.getPhone()) != null){
					//获取最后一次发送的通道下标
					int lastIndex = messageChannelMapHistory.get(message.getPhone()).getMessageChannel();
					channelIndex = lastIndex == channelList.size()- 1?0:lastIndex+1;
				}else{
					channelIndex = 0;
				}
				int returnFlag = channelList.get(channelIndex).sendMessage(message);
				
				if(returnFlag == -1){
					addToMessageChannelMapHistory(channelIndex,message,false);
					tpe.execute(this);
				}else{
					addToMessageChannelMapHistory(channelIndex, message,true);
				}
			}catch(Exception e){
				addToMessageChannelMapHistory(channelIndex,message,false);
				tpe.execute(this);
				e.printStackTrace();
			}
			
		}
	}
	
	
	/**
	 * 记录手机号与短信通道
	 * @param channelIndex
	 * @param message
	 */
	private static void addToMessageChannelMapHistory(int channelIndex,TextMessage message,boolean isSuccess){
    	MessageRecord mesRec = new MessageRecord();
    	mesRec.setMessageChannel(channelIndex);
    	mesRec.setPhoneNum(message.getPhone());
    	mesRec.setRecordTime(new Date());
    	mesRec.setSuccess(isSuccess);
		if(messageChannelMapHistory.get(message.getPhone())!=null){
			mesRec.setSendNum(messageChannelMapHistory.get(message.getPhone()).getSendNum()+1);
		}else{
			mesRec.setSendNum(1);
		}

    	messageChannelMapHistory.put(message.getPhone(), mesRec);
	}
	
	public static void main(String[] args) {
		try {
			SmsManager.getInstance().send("18515163440", "{\"code\":\"刘欢\",\"msg\":\"今日餐食计划完成\"}","plan",1);
		} catch (WrongPhoneException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
